﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using WebApplication1.EntitiesProcess.Tools;

namespace WebApplication1.EntitiesProcess
{
    public interface IEntityRepository<T> where T : class, IEntityBase, new()
    {
        /// <summary>
        /// 持久化数据
        /// </summary>
        Task<bool> SaveAsyn();

        /// <summary>
        /// 无限制提取所有业务对象
        /// </summary>
        /// <returns></returns>
        Task<IQueryable<T>> GetAllAsyn();

        /// <summary>
        /// 除了提取本身的对象数据集合外，还提取包含根据表达式提取关联的的对象的集合，
        /// </summary>
        /// <param name="includeProperties">需要直接提取关联类集合数据的表达式集合，通过逗号隔开</param>
        /// <returns></returns>
        Task<IQueryable<T>> GetAllIncludingAsyn(params Expression<Func<T, object>>[] includeProperties);

        /// <summary>
        /// 根据对象的ID提取具体的对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<T> GetSingleAsyn(Guid id);

        /// <summary>
        /// 根据对象的ID提取具体的对象，还提取包含根据表达式提取关联的的对象的集合，
        /// </summary>
        /// <param name="includeProperties">需要直接提取关联类集合数据的表达式集合，通过逗号隔开</param>
        /// <returns></returns>
        Task<T> GetSingleAsyn(Guid id, params Expression<Func<T, object>>[] includeProperties);

        /// <summary>
        /// 根据 Lambda 表达式提取具体的对象，实际上是提取满足表达式限制的集合的第一个对象集合
        /// </summary>
        /// <param name="predicate">布尔条件的 Lambda 表达式</param>
        /// <returns></returns>
        Task<T> GetSingleAsyn(Expression<Func<T, bool>> predicate);

        /// <summary>
        /// 根据 Lambda 表达式提取对象集合
        /// </summary>
        /// <param name="predicate">布尔条件的 Lambda 表达式</param>
        /// <returns></returns>
        Task<IQueryable<T>> FindByAsyn(Expression<Func<T, bool>> predicate);

        Task<bool> HasInstanceAsyn(Guid id);

        Task<bool> HasInstanceAsyn(Expression<Func<T, bool>> predicate);

        /// <summary>
        /// 根据内存中对应的数据集是否存在，自动决定采取添加或者编辑方法处理传入的对象，并直接持久化。
        /// </summary>
        /// <param name="entity"></param>
        Task<bool> AddOrEditAndSaveAsyn(T entity);

        /// <summary>
        /// 删除并保存。
        /// </summary>
        /// <param name="entity"></param>
        Task<DeleteStatusModel> DeleteAndSaveAsyn(Guid id);

        /// <summary>
        /// 按照指定的属性进行分页，提取分页后的对象集合，在本框架中，通常使用 SortCode
        /// </summary>
        /// <typeparam name="TKey">分页所依赖的属性</typeparam>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">每页对象的数量</param>
        /// <param name="keySelector">指定分页依赖属性的 Lambda 表达式</param>
        /// <returns></returns>
        Task<PaginatedList<T>> PaginateAsyn<TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> keySelector);

        /// <summary>
        /// 按照指定的属性进行分页，提取分页后的对象的集合
        /// </summary>
        /// <typeparam name="TKey">分页所依赖的属性</typeparam>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">每页对象的数量</param>
        /// <param name="keySelector">指定分页依赖属性的 Lambda 表达式</param>
        /// <param name="predicate">对象集合过滤 Lambda 表达式</param>
        /// <param name="includeProperties">指定的扩展对象属性的表达式集合，通过逗号隔离</param>
        /// <returns></returns>
        Task<PaginatedList<T>> PaginateAsyn<TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> keySelector, Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties);
    }
}
